// zc_queue.c

#include <libzc.h>

//// zc_queue
//struct zc_queue_t {
//    int size;
//    int length;
//
//    int head;
//    int tail;
//
//    void **data;
//};

// create.
struct zc_queue_t *zc_queue_create(int size)
{
    struct zc_queue_t *q = malloc(sizeof(struct zc_queue_t));
    if(q != NULL)
    {
        q->data = malloc(sizeof(void *) * size);
        if(q->data == NULL)
        {
            free(q);
            q = NULL;
        }
        else
        {
            q->size = size;
            q->length = 0;
            q->head = q->tail = 0;
        }
    }

    return q;
}

// realloc.
int zc_queue_realloc(struct zc_queue_t *q, int size)
{
    if(q->length > size)
    {
        return -1;
    }

    if(q != NULL)
    {
        void *p = malloc(sizeof(void *) * size);
        if(p != NULL)
        {
            memcpy(p, q->data, sizeof(void *)*q->length);
            free(q->data);
            q->size = size;
            q->data = p;
            return 0;
        }
    }

    return -1;
}

// add.
int zc_queue_add(struct zc_queue_t *q, void *d)
{
    if(q->length == q->size)
    {
        return -1;
    }

    q->data[q->tail] = d;
    q->length++;

    if(q->tail == q->size)
    {
        q->tail = 0;
    }
    else
    {
        q->tail++;
    }

    return 0;
}

// del.
void *zc_queue_del(struct zc_queue_t *q)
{
    void *d = NULL;

    if(q->length == 0 && q->tail == q->head)
    {
        return NULL;
    }

    d = q->data[q->head];
    q->length--;

    if(q->head == q->size)
    {
        q->head = 0;
    }
    else
    {
        q->head++;
    }

    return d;
}

// length.
int zc_queue_length(struct zc_queue_t *q)
{
    return q->length;
}

// is full. return 0 is full.
int zc_queue_isfull(struct zc_queue_t *q)
{
    return(q->size - q->length);
}

// clear.
void zc_queue_clear(struct zc_queue_t *q)
{
    q->head = q->tail = q->length = 0;

    return;
}

// destory.
void zc_queue_destory(struct zc_queue_t *q)
{
    if(q != NULL)
    {
        if(q->data != NULL)
        {
            free(q->data);
        }
        free(q);
    }

    return;
}
